home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr05 / xnot12a.zip / TTY.C < prev    next >
C/C++ Source or Header  |  1993-05-21  |  9KB  |  527 lines

  1. /*
  2.  * Mg 2b  (turboc 1.5/MSC 1.5)
  3.  *   IBM-PC and compatible BIOS based display driver.
  4.  *   - this will tend to be a bit slower than a driver that
  5.  *     writes directly to the memory mapped screen, but with
  6.  *     the large # of display adapters floating around, I'd
  7.  *     rather let the bios do the work.
  8.  * 
  9.  *     I DO recommend FANSI-CONSOLE which significantly speeds
  10.  *     up display bios calls, however.
  11.  *
  12.  * Bashed much to support, among other things, CURSES under U*x 
  13.  * and pre-queueable input everywhere not WINDOW_IO.
  14.  */
  15. #include "jam.h"
  16. #include "def.h"
  17. #include "keyname.h"
  18.     
  19. #ifndef CURSES            /* UNIX only */
  20. # include <dos.h>
  21. #else
  22. #include <signal.h>
  23. # ifdef SOL
  24. #  include <sys/resource.h>
  25.   struct rlimit rlim;
  26. # endif
  27. #endif
  28.  
  29. #define    BEL    0x07            /* BEL character.        */
  30. #define NORMAL  0x07
  31. #define REVERSE 0x70
  32.  
  33. extern    int    ttrow;
  34. extern    int    ttcol;
  35. extern    int    tttop;
  36. extern    int    ttbot;
  37. extern    int    tthue;
  38.  
  39. static int biocol = 0;
  40.  
  41. int    tceeol = 2;            /* Costs are set later */
  42. int    tcinsl = 5;
  43. int    tcdell = 5;
  44.  
  45. static    int insdel = TRUE;    /* Do we have both insert & delete line? */
  46. static int rendition = NORMAL;
  47.  
  48.  
  49. static int rn_(_move, (int row, int col));
  50. static int rn_(_ttinsl,(int row, int bot, int nchunk));
  51. static int rn_(_ttdell, (int row, int bot, int nchunk));
  52. static int rn_(napstart,(int amount,struct nap *sav));
  53. static int rn_(napchk, (struct nap *sav));
  54. static int rn_(nap, (int amount));
  55. static int rn_(putthechar,(unsigned char  c));
  56.  
  57. /*
  58.  * Initialize the terminal when the editor
  59.  * gets started up.
  60.  */
  61. ttinit() 
  62. {
  63. #ifdef CURSES
  64.   char *termid = (char *)getenv("TERM");
  65.  
  66.   initscr();
  67.   saveterm();
  68.   noecho();
  69.   nonl();
  70.   cbreak();
  71.   raw();
  72.   halfdelay(2);            /* non-blocking i/o at 1/10 sec intervals */
  73.   keypad(stdscr, TRUE);
  74.  
  75.   /* Sigh, on some devices the scroll feature looks
  76.   * crummy.  This should be a list, and also user-setable
  77.   */
  78.   idlok(stdscr, TRUE);
  79.   if (termid)
  80.     {
  81.       if ((strcmp("xterm", termid) == 0) || (strcmp("sun-cmd", termid) == 0))
  82.         idlok(stdscr, FALSE);
  83.     }
  84.  
  85.   wmove(stdscr, 0, 0);  
  86. #endif
  87.   return 1;
  88. }
  89.  
  90. /*
  91.  * Clean up the terminal, in anticipation of
  92.  * a return to the command interpreter.
  93.  */
  94. tttidy() 
  95. {
  96. #ifdef CURSES
  97.   resetterm();
  98.   echo();
  99.   nocbreak();
  100.   noraw(); 
  101.   nl();
  102.  
  103.   endwin();
  104. #endif
  105.   return 1;
  106. }
  107.  
  108. int ttputline(s)
  109. char *s;
  110. {
  111.   while (s && *s)
  112.     ttputc(*s++);
  113.   return(1);
  114. }
  115.  
  116. /*
  117.  * Move the cursor to the specified
  118.  * origin 0 row and column position.
  119.  */
  120. ttmove(row, col) 
  121. int row, col;
  122. {
  123.   ttcol = col;
  124.   ttrow = row;
  125.   _move(row, col);
  126.   return 1;
  127. }
  128.  
  129. /*
  130.  * Erase to end of page.
  131.  */
  132. tteeop() 
  133. {
  134. #ifdef CURSES
  135.   wclrtobot(stdscr);
  136. #else
  137.   ttdell(ttrow, nrow, nrow - ttrow);
  138. #endif
  139.   return 1;
  140. }
  141.  
  142. /*
  143.  * Insert nchunk blank line(s) onto the
  144.  * screen, scrolling the last line on the
  145.  * screen off the bottom.
  146.  */
  147. ttinsl(row, bot, nchunk) 
  148. int row, bot, nchunk;
  149. {
  150.   if (row == bot) 
  151.     {                            /* Case of one line insert is     */
  152.       ttmove(row, 0);        /*    special            */
  153.       tteeol();
  154.     }
  155.   
  156.   else
  157.     _ttinsl(row, bot, nchunk);
  158.   return 1;
  159. }
  160.  
  161. /*
  162.  * Delete nchunk line(s) from "row", replacing the
  163.  * bottom line on the screen with a blank line. 
  164.  */
  165. ttdell(row, bot, nchunk)
  166. int row, bot, nchunk;
  167. {
  168.     if (row == bot)
  169.       {                         /* One line special case    */
  170.     ttmove(row, 0);
  171.     tteeol();
  172.       }
  173.     else
  174.       _ttdell(row, bot, nchunk);
  175.     return 1;
  176. }
  177.  
  178. /*
  179.  * Switch to full screen scroll. This is
  180.  * used by "spawn.c" just before is suspends the
  181.  * editor, and by "display.c" when it is getting ready
  182.  * to exit.
  183.  */
  184. ttnowindow()
  185. {
  186.   return 1;
  187. }
  188.  
  189. /*
  190.  * Set the current writing color to the
  191.  * specified color. Watch for color changes that are
  192.  * not going to do anything (the color is already right)
  193.  * and don't send anything to the display.
  194.  */
  195. ttcolor(color) 
  196. register int color; 
  197. {
  198.   if (color != tthue) 
  199.     {
  200. #ifdef CURSES
  201.       wrefresh(stdscr);
  202. #endif
  203.       if (color == CTEXT) 
  204.       rendition = NORMAL;
  205.       else if (color == CMODE) 
  206.       rendition = REVERSE;
  207.       tthue = color;           /* Save the color.    */
  208. #ifdef CURSES
  209.       if (rendition == CMODE)
  210.         wattron(stdscr, A_REVERSE);
  211.       else
  212.         wattroff(stdscr, A_REVERSE);
  213. #endif
  214.     }
  215.   return 1;
  216. }
  217.  
  218. /*
  219.  * This routine is called by the
  220.  * "refresh the screen" command to try and resize
  221.  * the display. The new size, which must be deadstopped
  222.  * to not exceed the NROW and NCOL limits, it stored
  223.  * back into "nrow" and "ncol". Display can always deal
  224.  * with a screen NROW by NCOL. Look in "window.c" to
  225.  * see how the caller deals with a change.
  226.  */
  227. ttresize() 
  228. {
  229.   int flag = 0;
  230.  
  231.   setttysize();
  232.   return 1;
  233. }
  234.  
  235. ttputc(c)
  236. unsigned char c;
  237. {
  238.   if (c == '\b') 
  239.     {
  240.     if (biocol-1 > 0) 
  241.       {
  242.     _move(ttrow, biocol-1);
  243.       }
  244.     return (1);
  245.   }
  246.   else if (c == '\r') 
  247.     {
  248.       _move(ttrow, 0);
  249.       return (1);
  250.     }
  251.  
  252.   putthechar(c);
  253.   
  254.   if (biocol+1 >= ncol)
  255.     _move(ttrow + 1, 0);
  256.   else
  257.     _move(ttrow, biocol + 1);
  258. }
  259.  
  260.  
  261. /********************* bios calls, or manipulations ******************/
  262.  
  263.  
  264. /* Move cursor to row, col. next char goes here
  265. */
  266. static int _move(row, col) 
  267. int row, col;
  268. {
  269. #ifdef CURSES
  270.   biocol = col;
  271.   wmove(stdscr, row, col);
  272. #else
  273.   union REGS rg;
  274.   
  275.   biocol = col;
  276.   rg.h.ah = 2;        /* set cursor position function code */
  277.   rg.h.dl = col;
  278.   rg.h.dh = row;
  279.   rg.h.bh = 0;        /* set screen page number */
  280.   int86(0x10, &rg, &rg);
  281. #endif
  282.   return 1;
  283. }
  284.  
  285. /*
  286.  * Erase to end of line.
  287.  */
  288. tteeol() 
  289. {
  290. #ifdef CURSES
  291.   wclrtoeol(stdscr);
  292. #else
  293.   union REGS rg;
  294.   
  295.   rg.h.ah = 9;    /* write character/rendition */
  296.   rg.h.bh = 0;
  297.   rg.x.cx = ncol-biocol;
  298.   rg.h.al = ' ';
  299.   rg.h.bl = rendition;
  300.   int86(0x10, &rg, &rg);
  301. #endif
  302.   return 1;
  303. }
  304.  
  305. /*
  306.  * Make a noise.
  307.  */
  308. ttbeep() 
  309. {
  310. #ifdef CURSES
  311.   beep();
  312. #else
  313. # if 0
  314.   union REGS rg;
  315.   
  316.   rg.h.ah = 14;    /* write tty */
  317.   rg.h.al = BEL;
  318.   
  319.   int86(0x10, &rg, &rg);
  320. # else
  321.   ewprintf("BEEP BEEP!");    /* bios bell is TOO LONG AND LOUD */
  322. # endif
  323. #endif
  324.   return 1;
  325. }
  326.  
  327. /*
  328.  * Insert nchunk blank line(s) onto the
  329.  * screen, scrolling the last line on the
  330.  * screen off the bottom.
  331.  */
  332. static int _ttinsl(row, bot, nchunk)
  333. int row, bot, nchunk;
  334. {
  335. #ifdef CURSES
  336.  printf("_ttinsl NYI\n");
  337. #else
  338.   union REGS rg;
  339.   
  340.   rg.h.ah = 7;    /* scroll down */
  341.   rg.h.bh = 0x07;
  342.   rg.h.al = nchunk;
  343.   rg.h.ch = row;
  344.   rg.h.cl = 0;
  345.   rg.h.dh = bot;
  346.   rg.h.dl = ncol - 1;
  347.   
  348.   int86(0x10, &rg, &rg);
  349. #endif
  350.   return 1;
  351. }
  352.  
  353. /*
  354.  * Delete nchunk line(s) from "row", replacing the
  355.  * bottom line on the screen with a blank line. 
  356.  */
  357. static int _ttdell(row, bot, nchunk)
  358. int row, bot, nchunk;
  359. {
  360. #ifdef CURSES
  361.   printf("_ttdell NYI\n");
  362. #else
  363.   union REGS rg;
  364.   
  365.   rg.h.ah = 6;    /* scroll up */
  366.   rg.h.bh = 0x07;
  367.   rg.h.al = nchunk;
  368.   rg.h.ch = row;
  369.   rg.h.cl = 0;
  370.   rg.h.dh = bot;
  371.   rg.h.dl = ncol - 1;
  372.   
  373.   int86(0x10, &rg, &rg);
  374. #endif
  375.   return 1;
  376. }
  377.  
  378. static int putthechar(c)
  379. unsigned char c;
  380. {
  381. #ifdef CURSES
  382.   waddch(stdscr, c);
  383. #else
  384.   union REGS rg;
  385.  
  386.   rg.h.ah = 9;    /* write character/rendition */
  387.   rg.h.bh = 0;
  388.   rg.x.cx = 1;
  389.   rg.h.al = c;
  390.   rg.h.bl = rendition;
  391.   
  392.   int86(0x10, &rg, &rg);
  393. #endif
  394.   return 1;
  395. }
  396.  
  397. #ifdef MSC
  398. /***************************/
  399. /* MSDOS time functions    */
  400. /***************************/
  401.  
  402. /* waiting thing...
  403. */
  404. struct nap
  405. {
  406.   long napvalue;
  407.   long basetime;
  408. };
  409.  
  410. /* Apparantly Turbo C has a sleep library routine; MSC doesn't -jbs */
  411.  
  412. #define gettime(_a) ((((long)(_a.x.cx)) << 16)+_a.x.dx)
  413.  
  414. void sleep(amount)
  415. int amount;
  416. {
  417.   while (amount--)
  418. # if 1
  419.     nap(50);    /* not so long! */
  420. # else
  421.     nap(100);
  422. # endif
  423. }
  424.  
  425. /* nap in units of 100ths of seconds via busy loops. 
  426.  */
  427. static int nap(amount)
  428. int amount;
  429. {
  430.   struct nap tim;
  431.   napstart(amount, &tim);
  432.   while(napchk(&tim) == 0)
  433.     ;
  434.   return 1;
  435. }
  436.  
  437. static int napstart(amount,sav)
  438. int amount;
  439. register struct nap *sav;
  440. {
  441.   union REGS inregs, outregs;
  442.   int hunds, secs;
  443.   
  444.   inregs.h.ah = 0x2c;            /* get time */
  445.   int86(0x21, &inregs, &outregs);
  446.   
  447.   /* glitch in hardware RTC (time warp) makes this necessary 
  448.   */
  449.   inregs = outregs;
  450.   inregs.h.dl = 0;        /* seconds counter may be slow to increment */
  451.   if (inregs.h.dh > 0)
  452.     --inregs.h.dh;        /* paranoia */
  453.   if (inregs.h.cl > 0)
  454.     --inregs.h.cl;        /* more paranoia */
  455.   /* end of glitch handling */
  456.   
  457.   sav->basetime = gettime(inregs);    /* in case of wraparound */
  458.   
  459.   /* convert hundredths of seconds to future time structure 
  460.   */
  461.   secs = outregs.h.dh;
  462.   hunds = outregs.h.dl + amount;
  463.   
  464.   while (hunds >= 100) 
  465.     {
  466.       hunds -= 100;
  467.       ++secs;
  468.     }
  469.   outregs.h.dl = hunds;
  470.   while (secs >= 60) 
  471.     {
  472.       secs -= 60;
  473.       ++outregs.h.cl;            /* increment minutes */
  474.     }
  475.   outregs.h.dh = secs;
  476.   
  477.   /* check for minute and hour wraparound 
  478.    */
  479.   if (outregs.h.cl >= 60)
  480.     {
  481.       outregs.h.cl -= 60;
  482.       ++outregs.h.ch;            /* increment hours */
  483.     }
  484.   if (outregs.h.ch >= 24)
  485.     {
  486.       outregs.h.ch -= 24;
  487.     }
  488.   sav->napvalue = gettime(outregs);
  489.   return 1;
  490. }
  491.  
  492. static int napchk(sav)
  493. register struct nap *sav;
  494. {
  495.   union REGS inregs, outregs;
  496.   long current;
  497.   
  498.   inregs.h.ah = 0x2c;            /* get time */
  499.   int86(0x21, &inregs, &outregs);
  500.   
  501.   current = gettime(outregs);
  502.   
  503.   if(sav->napvalue > sav->basetime)
  504.     {
  505.       if (current >= sav->napvalue || current < sav->basetime)
  506.     return 1;
  507.     }
  508.   else if (current >= sav->napvalue && current < sav->basetime)
  509.     return 1;
  510.   return 0;
  511. }
  512.  
  513. #endif /* MSC */
  514.  
  515. ttwait()
  516. {
  517. #ifndef CURSES
  518.   struct nap timer;
  519.  
  520.   napstart(200, &timer);
  521.   while (napchk(&timer) == 0)
  522. #endif
  523.     if (mytypeahead())
  524.       return 0;
  525.   return 1;
  526. }
  527.